import UNetIdentity from "./UNetIdentity";

export module UNetMgr {
    
    export class RoomMessage {
        socket:UNet.Socket;

        //当前是第几帧
        public get frame(){
            return this._frame
        }

        rolePrefab : cc.Prefab = null;
        selfUUID : number = -1;
        sceneData : any = {}
        private _frame : number = 0;
        users : Array<any> = []

        allUser :Map<string,UNetIdentity>= new Map();
        constructor(socket){
            this.socket = socket;
            this.socket.On('game',this._RoomMessageDispatch,this)
            this.socket.On('frame',this._RoomFrameUpdate,this)
        }

        instantiateRole(){
            var role = cc.instantiate(this.rolePrefab);
            cc.find('Canvas').addChild(role);
            var idt = role.getComponent(UNetIdentity);
            return idt
        }

        _RoomMessageDispatch(v){
            console.log('_RoomMessageDispatch:',v)
            var e = v.ge
            if(e == 'ready'){ //自己举手准备
                var sceneUser = this.sceneData.scene_user
                var users = this.sceneData.users;
                for(var i=0; i<users.length; i++){
                    var cache = this.allUser.get(users[i].pid+'')
                    var idt = cache?cache : this.instantiateRole()
                    if(idt){
                        idt.OnSyncUserEnter(users[i]);
                        idt._uuid = users[i].pid
                        idt.isLocalPlayer = this.selfUUID == users[i].pid
                        idt.isLocalPlayer && idt.OnSelfPlayerInit();
                        this.allUser.set(idt._uuid.toString(),idt)
                    }
                }
                for(var pid in sceneUser){
                    var entity = this.allUser.get(pid);
                    entity.OnSyncSceneData(sceneUser[pid])
                }
            } else if(e == 'userEnter'){
                var user = v.v.user
                var cache = this.allUser.get(user.pid+'')
                if(!cache){
                    var cache = this.allUser.get(user.pid+'')
                    var idt = cache?cache : this.instantiateRole()
                    if(idt){
                        idt.OnSyncUserEnter(user);
                        idt._uuid = user.pid
                        this.allUser.set(idt._uuid.toString(),idt)
                    }
                } else {
                    cache.OnSyncUserEnter(user)

                    if(this.sceneData.scene_user){
                        cache.OnSyncSceneData(this.sceneData.scene_user[user.pid])
                    }
                    cache.OnSyncUserReActive()
                }
                
            } else if(e == 'join'){
                this.sceneData = v.v
                this.selfUUID = this.sceneData.pid
                UNetMgr.event.emit('join',v)
            } else if(e == 'userExit'){
                var idt = this.allUser.get(v.v.pid+'');
                if(idt){
                    this.sceneData.scene_user[v.v.pid] = idt.getOfflineStatus()
                    idt.OnSyncUserExit(v.v);
                    if(!UNetMgr.canOffline){
                        idt.node.destroy();
                        this.allUser.delete(v.v.pid+'')
                    }
                }
            }
        }
        _RoomFrameUpdate(v){
            this._frame = v.v.t;
            var arr = v.v.v;
            if(arr && Object.keys(arr).length){
                // console.log('_RoomFrameUpdate:',arr)
                for(var uid in arr){
                    var unet = this.allUser.get(uid+'');
                    if(unet){
                        unet.OnFrameUpdate(arr[uid]);
                    } else {
                        console.log('未找到的ID：',uid)
                    }
                }
            }
            UNetMgr.event.emit('frameUpdate')
        }
        releaseAll(){
            this.allUser.forEach((value,key)=>{
                value.node.destroy();
            })
            this.allUser.clear()
        }
    }

    /** 同步模式选择 */
    export enum SyncModel {
        /** 自己无延迟，对方看我延迟一帧，适用到网络稍微差点时，体验比较流畅 */
        SelfNoDelay,
        /** 全同步，全人物按帧同步，网络较差时，会一顿一顿的 */
        Full
    }

    export var socket: UNet.Socket;

    /** 同步模式 */
    export var model : SyncModel;

    /** 同步间隔，默认 1/10 */
    export var delay : number = 0.1;

    /** 支持用户再登陆 false不支持时，则离线直接删除用户数据 */
    export var canOffline = true;

    var loginData = {}
    export var event : UNet.Event = new UNet.Event()

    export var RolePrefab : cc.Prefab = null;

    export var room : RoomMessage = null

    export function StartConnect(connect:any,loginData:any){
        this.loginData = loginData
        this.socket = new UNet.Socket(connect);
        this.socket.Connect();
        this.socket.On(UNet.EventType.OPEN,_login,this)
        this.socket.On('loginSuccess',_onLoginSuccss,this)
        this.socket.On('loginError',_onLoginError,this)
        this.socket.On('close',_onClose,this)
        this.socket.On('error',_onError,this)
        this.socket.On('reconnect',_onReconnect,this)
        this.room = new RoomMessage(this.socket)
    }

    export function JoinRoom(roomId:string,pwd:string){
        UNetMgr.socket.Send('join',{roomId,pwd:pwd})
    }

    export function SendRoomMsg(key:string,v:any){
        UNetMgr.socket.Send('game',{ge:key,v:v})
        // console.log('SendRoomMsg:',Date.now(),v)
    }

    function _onLoginSuccss(v){
        UNetMgr.event.emit('loginSuccess',v)
    }

    function _onLoginError(){
        console.log('登陆失败')
    }
    
    function _login(){
        this.socket.Send(Object.assign({e:'login'},this.loginData));
    }
    function _onClose(){
        UNetMgr.event.emit('close')
        this.room.releaseAll()
    }
    function _onError(e){
        UNetMgr.event.emit('error',e)
    }
    function _onReconnect(){
        UNetMgr.event.emit('reconnect')
    }
}

